package com.lsu.app.controller;


import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lsu.app.bean.Menu;
import com.lsu.app.bean.Resource;
import com.lsu.app.bean.User;

import com.lsu.app.bean.UserTaste;
import com.lsu.app.config.target.RequestRoles;
import com.lsu.app.service.*;

import com.lsu.app.tool.R;
import com.lsu.app.tool.AESUtil;

import com.lsu.app.tool.jwtUtil;
import com.lsu.app.tool.uploadUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;


/**

 * @author hjj

 * @date 2023/10/16 18:56
 */
@RestController
@Slf4j
@CrossOrigin
@RequestMapping("/users")
public class UserController {
    @Autowired
    private HttpServletRequest request;


    @Value("${web.upload-path}")
    private String uploadPath;
    private final UserService userService;
    private final UserTasteService tasteService;
    private final LogService logservice;
    private final MenuService menuService;
    private final ResourceService resourceService;

    public UserController(UserService userService, UserTasteService tasteService, LogService logservice, MenuService menuService, ResourceService resourceService) {
        this.userService = userService;
        this.tasteService = tasteService;
        this.logservice = logservice;
        this.menuService = menuService;
        this.resourceService = resourceService;
    }


    @ApiOperation(value = "登录")
    @GetMapping("/login")
    public R<User> login(
            @ApiParam("账号") @RequestParam("username")String username,
            @ApiParam("密码") @RequestParam("password")String password,
            @ApiParam("登录类型1学生，2教师，3管理员") @RequestParam("type")Integer type){
        //检测账号是否已登录
//        if(jwtUtil.containLoginUserIds(userService.getIdByUsername(username))){
//            return R.err("该账号已登录");
//        }
        //获取数据库用户
        User user = userService.getUserByUsernameType(username, type);
        try {
            if(user==null){ //不存在
                switch (type){
                    case 1: return R.err("学生账号不存在！");
                    case 2: return R.err("教师账号不存在");
                    default:return R.err("账户不存在");
                }
            }else{
                if(AESUtil.eq(password,user.getPassword())){//校验密文密码
                    String role = userService.getRoleByUsername(user.getUsername());
                    //添加session
                    request.getSession().setAttribute("role",role);
                    request.getSession().setAttribute("username",username);
                    request.getSession().setAttribute("id",user.getId());
                    jwtUtil.addLoginUserIds(userService.getIdByUsername(username));
                    //添加token
                    user.setToken(jwtUtil.createToken(user.getId(),role));
                    user.setPassword("");//密码滞空
                    //获取头像位置
                    user.setImageUrl(resourceService.getHeadUrlByUorrIdAndType(user.getId()));
                    user.setTaste(userService.getTasteById(user.getId()));
                    logservice.createLog("USER_LOGIN","user-login->"+username,"成功登录");
                    return R.success(user);
                }else{
                    return R.err("密码不正确！");
                }
            }
        }catch (Exception e){
            return R.err(e.toString());
        }
    }

    @ApiOperation(value = "校验token是否可用")
    @GetMapping("/checkToken")
    public R<Boolean> checkToken(HttpServletRequest request){
        String token = request.getHeader("token");
        return R.success(jwtUtil.checkToken(token));
    }
    @ApiOperation(value = "登出")
    @GetMapping("/logout")
    public R<String> logout(){
        if(request.getSession().getAttribute("id")==null
        &&request.getSession().getAttribute("username")==null){
            return R.err("请勿重复登出");
        }
        String name  = userService.getNameById((Integer) request.getSession().getAttribute("id"));
        logservice.createLog("USER_LOGOUT","user-logout-"+request.getSession().getAttribute("username"),"");
        //清空会话
        request.getSession().removeAttribute("role");
        request.getSession().removeAttribute("username");
        jwtUtil.deleteLoginUserIds((Integer) request.getSession().getAttribute("id"));
        request.getSession().removeAttribute("id");
        return R.success(name+"-已退出登录");
    }

    @ApiOperation("菜单")
    @RequestRoles({"student","teacher","admin"})
    @GetMapping("/menu")
    public R<List<Menu>> getMenus(){
        List<Menu> list = menuService.getTopMenuByRole((String) request.getSession().getAttribute("role"));
        for (Menu menu : list) {
            menu.setSubmenu(menuService.getMenusByTopMenusId(menu.getId()));
        }
        return R.success(list);
    }
    @RequestRoles({"teacher","student"})
    @ApiOperation(value = "测试（学生和教师）")
    @GetMapping("te1")
    public R<String> te1(){
        return R.success("用户名为："+request.getSession().getAttribute("username")+"，角色是："+request.getSession().getAttribute("role"));
    }

    @ApiOperation(value = "创建用户")
    @PostMapping("/create")
    public R<String> createUser(
            @ApiParam("1学生（默认），2教师")@RequestParam("type")Integer type ,
            @ApiParam("账号(仅由数字和字母组成)") @RequestParam("username")String username,
            @ApiParam("昵称")@RequestParam("name")String name,
            @ApiParam("性别（女或男）")@RequestParam("sex")String sex,
            @ApiParam("简介（可为空）")@RequestParam("remake")String remake,
            @ApiParam("兴趣数组（可为空）")@RequestParam("taste") String[] taste,
            @ApiParam("密码")@RequestParam("password")String password,
            @RequestParam(value = "img",required = false) MultipartFile img
    ){
        try {
            if(type==null||username.equals("")||name.equals("")||(!sex.equals("男")&&!sex.equals("女"))||password.equals("")){
                return R.err("数据格式有误，请重新输入");
            }
            if(!Pattern.compile("[a-zA-Z0-9]+").matcher(username).matches()){
                return R.err("账号应仅由字母和数字组成");
            }
            if (userService.getIdByUsername(username) == null) {//判断账号是否存在
                User newUser = new User(username,AESUtil.encrypt(password),name,sex,LocalDateTime.now().toString(),LocalDateTime.now().toString(),remake);
                userService.save(newUser);
                R<String> result = uploadUtil.uploadMedia(img,uploadPath, String.valueOf(newUser.getId()));
                if(result.getCode()==0){
                    userService.removeById(newUser.getId());
                    return R.err("图片信息异常，创建失败");
                }
                //判断是否存在静态资源文件夹
                File orfile = new File(uploadPath.substring(0,uploadPath.length()-1));
                if(!orfile.exists()){//不存在则创建
                    orfile.mkdir();
                }
                //添加图片信息
                resourceService.save(new Resource(2,newUser.getId(),result.getData(), LocalDateTime.now().toString(),LocalDateTime.now().toString()));
                if(taste!=null&&taste.length>0){
                    //添加新兴趣
                    for (String str : taste) {
                        tasteService.save(new UserTaste(newUser.getId(),str,userService.getTasteNameValueByTasteName(str)));
                    }
                }else{
                    //若为空设置为其他
                    tasteService.save(new UserTaste(newUser.getId(),"其他",16));
                }
                if (type == 2) {
                    File file = new File(uploadPath+newUser.getId());
                    if(!file.exists()){
                        file.mkdir();
                    }
                    userService.setRoleByUser(newUser.getId(), 2);
                    logservice.createLog("USER_CREATE","teacher-"+username,username);
                } else { //除2以外的值 都写1
                    userService.setRoleByUser(newUser.getId(), 1);
                    logservice.createLog("USER_CREATE","student-"+username,username);
                }
                return R.success("创建成功");
            } else {
                return R.err("创建失败，用户账号已存在");
            }
        }catch (Exception e){
            e.printStackTrace();
            return R.err("服务器异常");
        }
    }

    @ApiOperation(value = "用户基本信息(不包括头像)修改")
    @PutMapping("/update")
    public R<String> updateUser(
//            @RequestBody User user
            @ApiParam("账号(仅由数字和字母组成)") @RequestParam("username")String username,
            @ApiParam("昵称")@RequestParam("name")String name,
            @ApiParam("性别（女或男）")@RequestParam("sex")String sex,
            @ApiParam("简介（可为空）")@RequestParam("remake") String remake,
            @ApiParam("兴趣数组（可为空）")@RequestParam("taste")String[] taste
    ){
        if(username==null||name==null||sex==null){
            return R.err("数据格式错误");
        }
        if(username.equals("")&&name.equals("")&&sex.equals("")){
            return R.err("基本数据不能为空");
        }
        //查询账户名是否可用
        R<String> r = checkUsername(username);
        if(r.getCode()==0){
            return r;
        }
        String us = request.getSession().getAttribute("username").toString();
        Integer userID = (Integer) request.getSession().getAttribute("id");
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getId,userID)
                .set(User::getUpdateTime,LocalDateTime.now().toString());

        //账号改变
        if(!username.equals(us)){//用户账号改变
            wrapper.set(User::getUsername,username);
            //更新session信息
            request.getSession().setAttribute("username",username);
        }
        if((sex.equals("男")||sex.equals("女"))&&!sex.equals(userService.getUserByUsername(us).getSex())){
            wrapper.set(User::getSex,sex);
        }
        wrapper.set(User::getName,name);
        wrapper.set(User::getRemake,remake!=null?remake:"");
        //删去原有记录
        tasteService.remove(new LambdaUpdateWrapper<UserTaste>().eq(UserTaste::getUserId,userID));
        //添加新兴趣
        if(taste!=null&&taste.length>0){
            for (String tas : taste) {
                tasteService.save(new UserTaste(userID,tas,userService.getTasteNameValueByTasteName(tas)));
            }
        }
        //更新用户信息
        userService.update(wrapper);
        //更新资源信息
//        resourceService.update(reWrapper);
        if(us.equals(username)){
            logservice.createLog("USER_UPDATE","update-user-"+us,"");
        }else{
            logservice.createLog("USER_UPDATE","update-user-"+us+"->"+username,"");
        }
        return R.success("更新成功！");
    }

    @ApiOperation("获取用户信息")
    @GetMapping("/self")
    public R<User> getUserBy(){
        //根据账户名获取user
        User user  = userService.getUserByUsername((String) request.getSession().getAttribute("username"));
        //获取头像位置
        user.setImageUrl(resourceService.getHeadUrlByUorrIdAndType(user.getId()));
        user.setTaste(userService.getTasteById(user.getId()));
        return R.success(user);
    }

    @ApiOperation("注销用户")
    @DeleteMapping ("/logoff")
    public R<String> deleteUser(){
        if(userService.getOne(new LambdaUpdateWrapper<User>().eq(User::getId,request.getSession().getAttribute("id"))).getState()==0){
            return R.err("该用户已注销");
        }
        userService.update(new LambdaUpdateWrapper<User>().eq(User::getId,request.getSession().getAttribute("id"))
                .set(User::getState,0));
        logout();
        return R.success("注销成功");
    }

    @ApiOperation(value = "检测用户账号名是否可用")
    @GetMapping("/check-username")
    public R<String> checkUsername(@ApiParam("被检测的账号")String username){
        if(userService.getUserByUsername(username)==null||request.getSession().getAttribute("username").equals(username)){
            return R.success("账号名可用");
        }else{
            return R.err("账号名不可用");
        }
    }
    @RequestRoles({"student","teacher"})
    @PostMapping("/image")
    @ApiOperation("更新头像")
    public R<String> setUserImage(
            @ApiParam("头像图片文件")@RequestParam("file") MultipartFile file) {
        if(file==null||!Objects.requireNonNull(file.getOriginalFilename()).contains(".")||file.isEmpty()){
            return R.err("图片格式有误");
        }
        Integer id = (Integer) request.getSession().getAttribute("id");
        String username = (String) request.getSession().getAttribute("username");
        R<String> stringR = uploadUtil.uploadMedia(file, uploadPath, String.valueOf(id));
        if(stringR.getCode()==1){
            //保存图片资源
            resourceService.update(new LambdaUpdateWrapper<Resource>().set(Resource::getUrl,stringR.getData()).set(Resource::getUpdateTime,LocalDateTime.now().toString())
                    .eq(Resource::getType,2).eq(Resource::getUorrId,userService.getIdByUsername(username)));
            logservice.createLog("USER_IMAGE_UPDATE","update-user-image-"+username,"");

            return R.success(resourceService.getHeadUrlByUorrIdAndType(id));
        }else{
            return stringR;
        }
    }

    @GetMapping("/getTastes")
    @ApiOperation("获取用户兴趣标签")
    public R<List<String>> getTastes(){
        return R.success(userService.getTastes());
    }

    @RequestRoles({"student","teacher"})
    @PutMapping("/updatePwd")
    @ApiOperation("修改密码")
    public R<User> putPwd(
        @ApiParam("用户id")@RequestParam("id")Integer id ,
        @ApiParam("旧密码")@RequestParam("oldPassword")String oldPassword,
        @ApiParam("新密码")@RequestParam("newPassword")String newPassword
    ) throws Exception {
        User user = userService.getById(id);
        if(user==null){
            return R.err("id不存在");
        }
        if(newPassword.equals("")){
            return R.err("新密码不能为空");
        }
        if(oldPassword.equals(newPassword)){
            return R.err("新旧密码一致");
        }
        if(AESUtil.eq(oldPassword,user.getPassword())){
            userService.update(new LambdaUpdateWrapper<User>().eq(User::getId,id).set(User::getPassword,AESUtil.encrypt(newPassword)));
            user.setImageUrl(resourceService.getHeadUrlByUorrIdAndType(user.getId()));
            user.setTaste(userService.getTasteById(user.getId()));
            logservice.createLog("USER_UPDATE",user+(String)request.getSession().getAttribute("username"),AESUtil.encrypt(newPassword));
            return R.success(user);
        }else{
            return R.err("原密码输入不正确！");
        }

    }
}
